# -*- coding:utf-8 -*-
# @Time :2022/8/12 10:18
# @File :  producer_yuqidong.py
# @Author :QiKangwei
# A14里面部署的是这个，但是仍处于测试阶段
import queue

from enum import Enum
import binascii
import json
import numpy as np
import pandas as pd
import requests
# from scapy.all import *
from api import utils
from api.pojie_A10.computing_method_A10 import XOR_verification, standardized_sampling, calculate_statistical_values, calculate_the_actual_temperature_value, real_time_value_of_pressure_and_velocity, \
    nozzle_temperature_1_8, actual_settings_pressure_speed
from api.pojie_A10.connect_mysql import connect_sql
from api.pojie_A10.producer_set_values_A10 import SampleProducer_set_A10
from api.pojie_A10.settings_pojie_A10 import chinese_source
from api.pojie_A10.producer_set_values_A10 import SampleProducer_set_A10
from api.serial import sample
from api.serial.rebuild_onehour import rebuild_onehour
from detecter import settings
import logging, threading, time, traceback, os, copy, struct
from datetime import datetime

logger = logging.getLogger('pojie_A10.producer_actual_values_A10')
set_yichang_time = 200


class SampleProducer_actual_values_A10(threading.Thread):
    __instance = None

    def __init__(self, ip, port, com, baud, current_mould):
        super().__init__()
        self.setName('SampleProducer_actual_values_A10')
        self.__running = threading.Event()  # 用于停止线程的标识
        self.q = queue.Queue(30000)  # 创建一个队列对象，里面可以存30000条数据
        self.recv_handle_queue = queue.Queue(30000)
        self.process_queue = settings.process_queue
        self.temporary_data = []
        self.__data_bytes = bytearray()  # 全局字节数组,串口数据缓冲区
        self.__data_bytes_part = bytearray()  # 全局字节数组,串口数据缓冲区
        self.new_circle_first = True  # 在这里初始值无论为True还是False对项目都没有影响，因为第一模数据是会被筛掉的(就先将其设为True)。当第二模数据开始时，会将这个值更新为True。
        self.socket_TF = True
        self.__sample_list = []  # 样本队列
        self.__sample_list1 = []  # 样本队列
        self.current_mould = current_mould
        # ##############   操作板相关   ###############
        self.time_yichang = ''
        self.is_yichang = True
        self.sample_frame_list_downsampling = []  # 周期帧数据列表
        self.Verification_List = ["02003C00", "02009E00", "02009001", "0200980100**4243"]
        self.Verification_List_dict = {"工艺曲线": "02003C00", "统计参数": "02009E00", "边缘计算": "02009001", "实际温度": "0200980100**4243"}
        self.Verification_List_set = ['02000900', '02008802']
        # 与上面字段一一对应，确定每种字段多少个字
        self.Verification_List_del_len = [120 * 2, 316 * 2, 800 * 2, 816 * 2]

        self.computer_board_timing = 0  # 统计参数 13、14位 周期计时
        self.signal_data_computer_board_timing = 0  # 信号数据 69、70位 周期计时
        self.statistical_parameter_row_identification = {"周期计时": "", "注射保压时间": "", "射出时间": "", "储料时间": "", "合模时间": "",
                                                         "合模低压时间": "", "合模高压时间": "", "开模时间": "", "开模位置": "", "射胶信号": "",
                                                         "射出终点": "", "射出监控": "", "射出起点": "", "转保压力": "", "最大储料转速": "",
                                                         "射退时间": "", "托模时间": "", "射出尖压": "", "储料尖压": "", "顶进时间": "",
                                                         "顶退时间": "", "取件时间": "", "最大射速": "", "保压时间": "", "冷却时间": "",
                                                         }  # 这里的设置值json文件可改动
        self.statistical_parameter_row_identification_True = {}

        # #############  电脑板统计参数  #############
        # 实时温度数据                                全过程
        self.real_time_temperature_data = {"tmp0": "", "tmp1": "", "tmp2": "", "tmp3": "", "tmp4": "", "tmp5": "", "tmp6": "", "tmp7": "", "tmp8": "", }  # 实时温度数据

        # 实时压力、速度  设定压力 设定速度                全过程
        self.actual_settings_pressure_speed_list = []

        # 实时机台信号数据                                  全过程
        self.processing_signal_data_list = []

        # ##############   分类采集   ###############
        self.conn = None
        self.collection = None
        self.thread_collection = None
        self.stop_sniffing = False

        # ##############   网口采集传输数据   ###############
        self.ip = ip
        self.port = port

        # ##############   串口采集传输数据   ###############
        self.com = com
        self.baud = baud

        self.scqd = []
        self.scjy = []
        self.cljy = []
        self.zdss = []

        self.global_shejiaobaoyafendaun = []
        self.machine_status = ""
        self.statistical_snapshot = []

    @classmethod
    def new_instance(cls, current_mould):
        # por1 = 51501  # 控制板——设定数据
        # por2 = 52501  # 操作板——实时数据
        cls.__instance = SampleProducer_actual_values_A10("192.168.3.124", 8888, None, None, current_mould)  # 这里传入的ip和端口根本就没有用，因为后面监听的是网口。
        return cls.__instance

    @classmethod
    def get_instance(cls):
        return cls.__instance

    def get_sample_list(self):
        return self.__sample_list

    def get_sample_list1(self):
        return self.__sample_list1

    def is_producer_running(self):
        return self.__running.is_set()

    def begin(self):
        if not self.is_alive():
            self.__running.set()
            self.setDaemon(False)  # 不设置守护线程, 就算websocket挂了也继续收集数据,处理数据, 存入临时文件中, 直到停止本工单才算停止此线程
            self.start()
            t = threading.Thread(target=self.handle_temporary_data)
            t.setDaemon(False)
            t.start()
            # threading.Thread(target=self.save_statis_snap).start()

    # def save_statis_snap(self):
    #     while True:
    #         if len(self.statistical_snapshot)>0:
    #             try:
    #                 top_stats=self.statistical_snapshot.pop(0)
    #
    #                 # self.display_top(top_stats)
    #                 with open("//usr//local//src//webroot//detecter//data//test.txt", "a+") as f:
    #                     f.write(str(top_stats[0]))
    #                     f.write(str(top_stats[1]))
    #                     f.write(str(top_stats[2])+'\n'+'\n')
    #                 print("成功写入！")
    #             except:
    #                 logger.info(traceback.format_exc())

    # 其实这个函数可以不写，项目中期的时候提出 采集线程一直工作
    def stop(self):
        if self.is_alive():
            self.stop_sniffing = True
            self.socket_TF = False
            # if self.ip:
            #     self.conn.close()
            # self.collection.close()
            self.__running.clear()  # 设置为False

    def transfer_sample(self, current_sample):
        current_mould = self.current_mould
        current_consumer = current_mould.consumer
        if current_consumer.is_consumer_running():  # 如果消费者正在运行
            self.__sample_list.append(current_sample)
        else:  # 如果消费者未处于运行中
            logger.info('消费者consumer未处于运行中')
            utils.undetect_handler(current_mould, current_sample, current_mould.unassigned_file)
            # 如果consumer未运行超过1小时，则自动建模
            if self.is_yichang:
                self.time_yichang = time.time()
                self.is_yichang = False
            # 如果异常超过1小时，则自动建模
            if round(time.time() - self.time_yichang, 2) >= set_yichang_time:
                # close_consumer(current_mould)
                rebuild_onehour(current_mould.mould_code)

    def run(self):
        global sample_frame_list_TF, sample_frame_list_for_other_TF
        is_first_sample = True
        pressure_size = 8  # 用作判别、确认字段信息的长度
        frame_rate = 5  # 机台采集数据的频率(计算周期字段的数据频率)，1s有多少帧数据传过来      帧数可以被算出来   由于网络因素或其他，这个值可以是动态变化的
        frame_bytes_list = []  # 异常帧数据列表
        last_50_cycles = []  # 存最近50个周期，以用作计算标准周期
        zhenshu = 10  # 测试帧数  需要测试多少帧
        data_flag = False
        standard_cycle = 0
        sample_frame_list_for_other_TF = False
        sample_frame_list_TF = False
        self.thread_collection = threading.Thread(target=self.receive_packets, args=(self.socket_TF,))
        self.thread_collection.start()
        while self.__running.is_set():
            while self.q.qsize() >= 1:  # 队列里面有一条以上的数据
                # snapshot1=tracemalloc.take_snapshot()
                # frame_bytes = data_bytes[0:int(16 / 2)].hex().upper()  # 16位
                data_bytes = self.q.get()  # 得到的是一个字节型数据
                frame_bytes = data_bytes[0:int(16 / 2)].hex().upper()  # 16位
                if frame_bytes[:10] == self.Verification_List[3][:10]:
                    whether_to_parse, del_size = True, int(self.Verification_List_del_len[3] / 2)
                else:
                    whether_to_parse, del_size = self.verify_dictionary(frame_bytes[:8], self.Verification_List, self.Verification_List_del_len)
                # 防止帧数据不完整
                if len(data_bytes[0:del_size]) != del_size:
                    whether_to_parse = False
                    # del_size = len(data_bytes[0:del_size])
                    logger.info("帧数据数据不完整")

                if not data_flag:
                    logger.info("SampleProducer_actual_values_A10 received data!")
                    data_flag = True
                # 若标识字段在所要解析的列表中时，根据该标识拿到字节长度即是后面所删除的字长度
                if whether_to_parse:
                    frame_bytes = data_bytes.hex().upper()
                    # 数据过滤、异或校验
                    if XOR_verification(frame_bytes[4:-6]) == frame_bytes[-6:-4]:
                        # print('异或校验通过')
                        # 不是自动、半自动状态的    不进行采集
                        if frame_bytes[24:26] == "03":
                            self.machine_status = "半自动"
                        elif frame_bytes[24:26] == "09":
                            self.machine_status = "全自动"
                        elif frame_bytes[24:26] == "00":
                            self.machine_status = "手动"
                        if frame_bytes[:pressure_size] == "02009001" and frame_bytes[24:26] not in ["03", "09"]:
                            logger.info("不是自动、半自动状态，不进行采集")
                            self.del_data()
                            self.actual_settings_pressure_speed_list = []
                            self.processing_signal_data_list = []
                            is_first_sample = True
                            continue
                        # 将数据添加到指定列表
                        try:
                            self.add_data_to_list(frame_bytes, pressure_size)
                        except:
                            logger.info(traceback.format_exc())

                        # 检测缓存数据量，如果数据存量有30分钟帧数量，则清理压力帧数据缓存列表
                        if len(self.processing_signal_data_list) >= frame_rate * 60 * 30 or len(self.actual_settings_pressure_speed_list) >= frame_rate * 60 * 30:  # 一秒多少帧  一分钟60秒  以30分钟做限制
                            # data_bytes.clear()
                            self.del_data()
                            self.actual_settings_pressure_speed_list = []
                            self.processing_signal_data_list = []
                            is_first_sample = True
                            logger.info("清理缓存")
                            continue
                        # frame_list_len_for_other = len(self.actual_settings_pressure_speed_list)
                        # if frame_list_len_for_other >= 5:
                        #     # print('------------------------------设置实时速度压力速度列表的值大于5---------------------------------------------------')
                        #     check_frame_list_for_other = self.actual_settings_pressure_speed_list[frame_list_len_for_other - 5:frame_list_len_for_other]
                        #     if self.is_product_begin_for_other(check_frame_list_for_other):
                        #         sample_frame_list_for_other = self.actual_settings_pressure_speed_list[:frame_list_len_for_other - 4]  # 包含最后一帧
                        #         # 当合模信号确认后，直接删除对应列表中的存储信息
                        #         del self.actual_settings_pressure_speed_list[0:len(self.actual_settings_pressure_speed_list) - 4]  # 保留下一帧开始的4帧没有丢失
                        #         # print('------------------------------设置实时速度压力速度列表取到一个周期的值---------------------------------------------------', len(sample_frame_list_for_other))
                        #
                        #         sample_frame_list_for_other_TF = True

                        frame_list_len = len(self.processing_signal_data_list)
                        if frame_list_len >= 5:
                            check_frame_list = self.processing_signal_data_list[frame_list_len - 5:frame_list_len]
                            if self.is_product_begin(check_frame_list):
                                sample_frame_list = self.processing_signal_data_list[:frame_list_len - 4]  # 包含最后一帧
                                # 当合模信号确认后，直接删除对应列表中的存储信息
                                del self.processing_signal_data_list[0:len(self.processing_signal_data_list) - 4]  # 保留下一帧开始的4帧没有丢失
                                sample_frame_list_TF = True
                                logger.info('边缘计算的合模信号结束！')

                        frame_list_len_for_other = len(self.actual_settings_pressure_speed_list)
                        if frame_list_len_for_other >= 5:
                            # print('------------------------------设置实时速度压力速度列表的值大于5---------------------------------------------------')
                            check_frame_list_for_other = self.actual_settings_pressure_speed_list[frame_list_len_for_other - 5:frame_list_len_for_other]
                            if self.is_product_begin_for_other(check_frame_list_for_other):
                                sample_frame_list_for_other = self.actual_settings_pressure_speed_list[:frame_list_len_for_other - 4]  # 包含最后一帧
                                # 当合模信号确认后，直接删除对应列表中的存储信息
                                del self.actual_settings_pressure_speed_list[0:len(self.actual_settings_pressure_speed_list) - 4]  # 保留下一帧开始的4帧没有丢失
                                # print('------------------------------设置实时速度压力速度列表取到一个周期的值---------------------------------------------------', len(sample_frame_list_for_other))
                                sample_frame_list_for_other_TF = True
                                logger.info("工艺参数的合模信号结束!")
                                if sample_frame_list_for_other_TF and sample_frame_list_TF:
                                    sample_frame_list_for_other_TF = False
                                    sample_frame_list_TF = False
                                else:
                                    continue

                                sample_id = self.current_mould.add_sample()
                                # 除掉第一个样本(第一个样本无法收集到全部帧信息)
                                if is_first_sample:
                                    is_first_sample = False
                                    logger.info("采集到第一个样本，不计入，跳过")
                                else:
                                    try:
                                        if len(last_50_cycles) < zhenshu:
                                            logger.info("周期列表个数{}，未到{}，周期帧数不做限制".format(len(last_50_cycles), zhenshu))
                                            last_50_cycles.append(len(sample_frame_list) / frame_rate)  # 大于标准周期的两倍，还是要参与标准周期的计算吗？
                                            if len(last_50_cycles) == zhenshu:
                                                standard_cycle = self.statistical_cycle_interval(last_50_cycles, zhenshu)

                                        elif len(last_50_cycles) == zhenshu:
                                            logger.info("周期列表个数{}，到{}，周期帧数限制".format(len(last_50_cycles), zhenshu))
                                            last_50_cycles.append(len(sample_frame_list) / frame_rate)
                                            last_50_cycles.pop(0)
                                            standard_cycle = self.statistical_cycle_interval(last_50_cycles, zhenshu)
                                            logger.info("落在多数区间的上限值是{}s".format(standard_cycle))

                                        # 大于标准周期的2倍，并且周期列表中有10个样本   不传输周期数据
                                        if len(sample_frame_list) >= standard_cycle * frame_rate * 2 and len(last_50_cycles) == zhenshu:
                                            logger.info("2倍区间上限是{}".format(standard_cycle * frame_rate * 2))
                                            logger.info("该样本帧数长度为{}".format(len(sample_frame_list)))
                                            # 将该样本的帧数据存入文件夹中
                                            # with open("//usr//local//src//webroot//detecter//data//error_sample.csv", "w") as f:
                                            with open(os.path.join(os.getcwd(), "error_sample.csv"), "w") as f:
                                                f.writelines("产品id为{}的帧数据量异常，存入异常文件中，不向Java传输周期数据".format(sample_id))
                                                for i in frame_bytes_list:
                                                    f.writelines(i)
                                                    f.writelines("\n")
                                            logger.info("产品id为{}的帧数据量异常，存入异常文件中，不向Java传输周期数据".format(sample_id))
                                            self.del_data()
                                            self.actual_settings_pressure_speed_list = []
                                            self.processing_signal_data_list = []
                                            continue
                                        self.sample_frame_list_downsampling = standardized_sampling([list(j) for j in list(np.array(sample_frame_list)[:, :11])])
                                        self.add_increment(float(self.statistical_parameter_row_identification_True['周期计时']) * 80)  # 计算的周期误差较大  换到统计标识行调用
                                        try:

                                            # 只取 射胶段 和 保压段
                                            df = pd.DataFrame(sample_frame_list_for_other)
                                            sample_frame_list_for_other = df.loc[(df[3] == "00") | (df[3] == "01")].values.tolist()
                                            # 设定压力、速度数据列表，需要将 实时数据 融合在一起
                                            set_data = [list(j) for j in list(np.array(sample_frame_list)[:, [i for i in range(11)]])]
                                            df = pd.DataFrame(set_data)
                                            df[7] = df[7].apply(lambda x: eval(str(x)))  # 第7列  射胶保压
                                            set_data = df.loc[df[7] > 10].values.tolist()  # 为什么要要筛选第七列的值大于10的呢？,因为可能某条数据并不是射胶保压阶段相关的信息，第七列的值就是0

                                            # 先将射胶保压分段拿到
                                            self.global_shejiaobaoyafendaun = [0]
                                            # 更新全局的射胶保压分段。这个分段是根据实时的射胶、保压10Hz的数据来分段的，后续的设定值要以它为标准

                                            actual_location = list(np.array(sample_frame_list_for_other)[:, 3])
                                            shejiaoduan = 0
                                            baoya_duan = 0
                                            for i in range(len(actual_location)):
                                                if actual_location[i] == "00":
                                                    shejiaoduan = i
                                                elif actual_location[i] == "01":
                                                    baoya_duan = i
                                            self.global_shejiaobaoyafendaun.append(shejiaoduan)  # 这里其实是进行了一个射胶段和保压段的分段标识[0,shejiaodaun,baoya_duan]
                                            self.global_shejiaobaoyafendaun.append(baoya_duan)


                                            sample_frame_list = self.synchronous_setting_of_real_time_values(set_data,
                                                                                                             sample_frame_list_for_other)  # 传进去的sample_frame_list_for_other就只有射胶段和保压段的数据。得到的是每隔17条取一条的帧列表
                                            logger.info("射胶结束点")
                                            # 往服务器发送当前样本的数据,服务器要保存每个产品的数据
                                            current_sample = sample.ProductSample(sample_id, sample_frame_list)  # 得到一个产品样本实例，这里穿进去的sample_frame_list是规整过频率列表，每秒10HZ
                                            # 保存最近一小时的数据
                                            current_sample.save_in_file(self.current_mould.one_hour_temp_file)
                                            # 处理当前样本
                                            self.current_mould.prod_sample = current_sample  # 将这模产品赋值给当前模具
                                            self.transfer_sample(current_sample)
                                            # 限制__sample_list1的数量，确保在传输数据的线程挂掉后不影响producer，不过多占用内存
                                            if len(self.__sample_list1) < 100:
                                                self.__sample_list1.append(current_sample)
                                            else:
                                                self.__sample_list1.pop(0)
                                                self.__sample_list1.append(current_sample)
                                        except Exception as e:
                                            # self.__pressure_frame_list = []
                                            last_50_cycles = []
                                            is_first_sample = True
                                            logger.error(f'样本生成有效信息失败,舍去该样本,{e}')
                                            logger.info(traceback.format_exc())
                                            continue

                                        # ############################    上传周期过后的操作     ########################

                                        # 写入配置文件
                                        f = open(os.path.join(os.path.dirname(__file__), "computer_version.json"), 'w', encoding='utf8')
                                        json.dump(self.statistical_parameter_row_identification_True, f, ensure_ascii=False)
                                        f.close()

                                        # 根据excel需求表，表一、表二是需要采集的数据，表三是存入数据库的数据字段排版
                                        # 数据集的升采样和降采样、以及数据到consumer分析中
                                        # 一、操作板设置值
                                        set_value = SampleProducer_set_A10.get_instance().set_field_dictionary_supply
                                        set_value = {k: set_value[v] if v in set_value.keys() else None for k, v in chinese_source.items()}
                                        # 二、电脑板统计值
                                        # statistical_value = calculate_statistical_values(self.processing_signal_data_list, self.statistical_parameter_row_identification_True)
                                        self.statistical_parameter_row_identification_True["射胶信号"] = ""
                                        self.statistical_parameter_row_identification_True["机台状态"] = self.processing_signal_data_list[-1][11]
                                        statistical_value = self.statistical_parameter_row_identification_True
                                        # 三、温度实时实际值
                                        actual_temperature_value = calculate_the_actual_temperature_value(self.real_time_temperature_data)
                                        # 四、压力速度设定值、实时值
                                        curve_value = real_time_value_of_pressure_and_velocity(sample_frame_list_for_other)
                                        machine_code = settings.MACHINE_CODE.lower()
                                        mode_code = self.current_mould.mould_code
                                        # 将字典中的内容上传至数据库
                                        connect_sql("python_machine", machine_code).insert_mysql_machine(datetime.now(), machine_code, mode_code, str(set_value), str(statistical_value),
                                                                                                         str(actual_temperature_value), str(curve_value), )
                                        logger.info("数据传输成功！！！")
                                    except:
                                        logger.error(traceback.format_exc())
                                # 请注意，这个del_data管理的四个列表要记得清空，否则会不断占用内存。目前在统计参数那里进行了清空
                                # self.del_data()
                    else:
                        print('异或校验没有通过')
                else:
                    # logger.warning('数据校验出错: %s' % frame_bytes)
                    # print('数据校验出错: %s' % frame_bytes)
                    pass

        # 结束清空
        self.stop()
        logger.warning("样本采集线程SampleProducer_actual_values_A10退出")

    def receive_packets(self, socket_TF):
        while self.socket_TF:
            try:
                self.recv_handle_queue.put(self.process_queue.get())
            except Exception as e:
                pass

            # if is_first_collection:
            #     try:
            #         inter = "enp3s0"
            #         sock = socket.socket(socket.PF_PACKET, socket.SOCK_DGRAM, socket.htons(0x0003))
            #         sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)  # 端口复用      True的作用是设置 SO_REUSEADDR 选项为启用状态，允许地址重用。
            #         sock.bind((inter, 0))
            #         sock.settimeout(30)  # 如果30秒没有接收到数据，就报错
            #         logger.info("样本采集线程SampleProducer_actual_values_A10开始监听数据！！！")
            #         is_first_collection = False
            #     except:
            #         continue
            # try:
            #     data, addr = sock.recvfrom(10240)
            #
            #     self.recv_handle_queue.put(data)
            #
            # except:
            #     sock.close()
            #     is_first_collection = True
            #     time.sleep(5)
            #     logger.info(traceback.format_exc())
            #     # 会出现socket接收不到数据的情况，如果重启python就可以接收到数据了。这里进行一些处理
            #     # 10个数据，大概是六七分钟左右，长达七分钟接收不到数据，就需要进行重启。七分钟是随意的，这个时间不长也不短。
            #     if len(socket_baocuo_jiange) < 10:  # 不到10个数据就只添加，不做处理
            #         socket_baocuo_jiange.append(datetime.now())
            #         with open("//var//log//python_zhengchang_chongqi_jilu.log", "a+") as f:
            #             f.write(f'{datetime.now()},{str(len(socket_baocuo_jiange))},{traceback.format_exc()}' + '\n')
            #     else:
            #         socket_baocuo_jiange.pop(0)  # 保持长度为10。如果在10条数据之内，socket正常了，就不会执行重启，列表中的数据不会被清除掉。下次再报异常，会积累，所以要pop
            #         socket_baocuo_jiange.append(datetime.now())
            #         # 进行判断并重启
            #         difference_in_seconds = socket_baocuo_jiange[-2] - socket_baocuo_jiange[-3]
            #         if difference_in_seconds.total_seconds() < 120:  # 如果最近的第二、三条记录时差小于120秒
            #             if (socket_baocuo_jiange[-1] - socket_baocuo_jiange[-3]).total_seconds() < 240:  # 如果最近的第一、三条记录时差小于240秒
            #                 # 两个时差都满足时，说明最近的超时记录是最新的
            #                 logger.info('socket长时间接收不到数据，执行了重启')  # 注意这里，由于系统里面有一个检测项目的脚本也有启动python的功能，有几率在同一时刻(极短时间段内)，各自启动一个python项目，
            #                 with open("//var//log//python_zhengchang_chongqi_jilu.log", "a+") as f:
            #                     f.write(f'{datetime.now()},socket长时间接收不到数据，执行了重启' + '\n')
            #                 subprocess.Popen(["bash", '/home/whhd/start.sh'])  # 开启一个新的进程进行重启
            #                 # 考虑增加一个检测python项目的脚本，用于保证只有一个项目在运行

    def handle_temporary_data(self):
        while True:
            if self.recv_handle_queue.qsize() > 0:
                try:
                    data = self.recv_handle_queue.get()
                    frame_bytes1 = data.hex().upper()
                    # with open("//usr//local//src//webroot//detecter//data//test.txt", "a+") as f:##不要在这里进行写操作，耗时严重，会严重丢帧！！！！！！！！！！！
                    #     f.write(frame_bytes)
                    #     f.write("哈哈哈哈哈\n")
                    #     print("成功写入！")
                    frame_bytes = frame_bytes1[56:]  # 这前面56个字节是包头等信息，从索引56开始后面是我们需要的data
                    temp_bytes = bytes.fromhex(frame_bytes)  # 将16进制转成字节类型
                    frame_bytes = temp_bytes[0:int(16 / 2)].hex().upper()  # 16位
                    if (frame_bytes[:10] == self.Verification_List[3][:10] and frame_bytes[-4:] == self.Verification_List[3][-4:]) or temp_bytes[0:int(8 / 2)].hex().upper() in self.Verification_List:
                        try:
                            self.q.put(temp_bytes)
                            if self.q.qsize() > 29000:
                                logger.info('self.q出现数据累积，已超过29000，为{}'.format(self.q.qsize()))
                        except Exception as e:
                            logger.info(e)
                    if frame_bytes1[24:32] == "C0A803D3" and frame_bytes[:8] in self.Verification_List_set:  # C0A803D3是一个源地址
                        SampleProducer_set_A10.get_instance().q_set.put(temp_bytes)
                except:
                    logger.info(traceback.format_exc())

    def synchronous_setting_of_real_time_values(self, set_data, sample_frame_list_for_other):
        # 一、8Hz的9001合并到17Hz的3C00中，8Hz到17Hz，取螺杆位置曲线数据
        # 二、17Hz二维数据缩放到10Hz并返回

        # ['2024-02-18 15:24:26.364260', 1708241066364, 0, 10, 10, 0, 0.0, 0, 0, 0, 1, 0]
        # 时间、时间戳、帧序列、设定压力、设定速度、实际压力、实际螺杆、射胶（保压）、储料、射退、合模（开模）、实际速度

        all_list = []
        # 压力速度实际设置值和螺杆位置值 统一帧数
        actual_settings_pressure_speed_list = sample_frame_list_for_other
        actual_pressure = list(np.array(actual_settings_pressure_speed_list)[:, 4])
        actual_speed = list(np.array(actual_settings_pressure_speed_list)[:, 5])
        set_pressure = list(np.array(actual_settings_pressure_speed_list)[:, 6])
        set_speed = list(np.array(actual_settings_pressure_speed_list)[:, 7])

        all_list.append(list(np.array(actual_settings_pressure_speed_list)[:, 0]))
        all_list.append(list(np.array(actual_settings_pressure_speed_list)[:, 1]))
        all_list.append(list(np.array(actual_settings_pressure_speed_list)[:, 2]))
        all_list.append(set_pressure)
        all_list.append(set_speed)
        all_list.append(actual_pressure)

        # 关于螺杆位置对齐的算法
        # 先放大字段
        actual_loc = []
        for i in range(len(set_data)):  # 遍历螺杆位置字段
            for j in range(len(all_list[0])):  # 遍历实际压力速度
                actual_loc.append(set_data[i][6])  # 下标为6的是螺杆位置

        # 再缩小字段
        actual_loc_new = []
        for i in range(0, len(actual_loc), len(set_data)):
            actual_loc_new.append(actual_loc[i])

        all_list.append(actual_loc_new)  # 实际螺杆
        all_list.append([1 if i == "00" else 0 for i in list(np.array(actual_settings_pressure_speed_list)[:, 3])])  # 射胶（保压）
        # all_list.append([1 if i in ["00", '01'] else 0 for i in list(np.array(actual_settings_pressure_speed_list)[:, 3])])  # 射胶（保压）
        all_list.append([1 if i == "04" else 0 for i in list(np.array(actual_settings_pressure_speed_list)[:, 3])])  # 储料
        all_list.append([1 if i == "07" else 0 for i in list(np.array(actual_settings_pressure_speed_list)[:, 3])])  # 开模
        all_list.append([1 if i == "06" else 0 for i in list(np.array(actual_settings_pressure_speed_list)[:, 3])])  # 合模
        all_list.append(actual_speed)  # 实际速度

        aaa = np.array(all_list).T

        # # 规整频率到10Hz  ，  从17Hz到10Hz
        # aaa_170Hz = []
        # for i in range(len(aaa)):
        #     for j in range(10):
        #         aaa_170Hz.append(aaa[i])
        #
        # aaa_10Hz = []
        # for i in range(0, len(aaa_170Hz), 17):
        #     aaa_10Hz.append(aaa_170Hz[i])
        # aaa = aaa_10Hz
        #
        # self.global_shejiaobaoyafendaun = [0]
        # # 更新全局的射胶保压分段。这个分段是根据实时的射胶、保压10Hz的数据来分段的，后续的设定值要以它为标准
        # actual_location = list(np.array(aaa)[:, 7])  # 射胶保压的分段要根据降频后的数据来取。虽然不明白为什么要降频
        # shejiaoduan = 0
        # baoya_duan = 0
        # for i in range(len(actual_location)):
        #     if actual_location[i] == "1":
        #         shejiaoduan = i
        #     elif actual_location[i] == "0":
        #         baoya_duan = i
        # self.global_shejiaobaoyafendaun.append(shejiaoduan)  # 这里其实是进行了一个射胶段和保压段的分段标识[0,shejiaodaun,baoya_duan]
        # self.global_shejiaobaoyafendaun.append(baoya_duan)


        df = pd.DataFrame(aaa)
        for i in range(1, len(aaa[0])):
            df[i] = df[i].apply(lambda x: eval(str(x)))

        return df.values.tolist()

    def del_data(self):
        # 下面这两行代码千万不要打开，因为取到一个周期的数据时，当时就删除了，如果调用这个函数再次删除时，就会导致把下一个周期的数据删除。造成多次删除
        # del self.processing_signal_data_list[0:len(self.processing_signal_data_list) - 4]  # 保留下一帧开始的4帧没有丢失
        # del self.actual_settings_pressure_speed_list[0:len(self.actual_settings_pressure_speed_list) - 4]  # 保留下一帧开始的4帧没有丢失
        self.scqd, self.scjy, self.cljy, self.zdss = [], [], [], []

    # 初始化

    # 信息分类添加、集成
    def add_data_to_list(self, frame_bytes, pressure_size):
        frame_arr = []
        # print('前八位：值————————————————————————————————————————————————————————————————————————')
        # 去找对应方法解析
        if frame_bytes[:10] == "0200980100" and frame_bytes[12:16] == "4243":  # 实时温度数据                   全过程
            # if frame_bytes[:10] == self.Verification_List_dict['实际温度'][:10] and frame_bytes[12:16] == self.Verification_List_dict['实际温度'][-4:]:  # 实时温度数据                   全过程
            self.real_time_temperature_data = nozzle_temperature_1_8(frame_bytes, self.real_time_temperature_data)

        elif frame_bytes[:pressure_size] == "02003C00":  # 处理实时压力、速度、设置压力、设置速度            全过程
            # elif frame_bytes[:pressure_size] == self.Verification_List_dict['工艺曲线']:  # 处理实时压力、速度、设置压力、设置速度            全过程
            # self.jishu += 1
            # print(self.jishu)
            # i = 0
            # self.actual_settings_pressure_speed_list.append(actual_settings_pressure_speed(frame_bytes, i))
            p = 1  # 取17 * 5 帧  其实是可以取17*6帧的，但考虑到会有06 00 00 00 00的情况，而且很多地方取值5个数组进行校验，所以选取 乘以5 帧
            exemption_from_verification = False
            for i in range(p):
                res = actual_settings_pressure_speed(frame_bytes, i)
                # with open("//usr//local//src//webroot//detecter//data//test576.txt", "a+") as f:  ##不要在这里进行写操作，耗时严重，会严重丢帧！！！！！！！！！！！
                #     f.write(frame_bytes[:32])
                #     f.write("\n")
                #     print("成功写入！")

                # res[3] != "06" 是因为在判断一个周期的时候用到了合模 06 这个信号，而在原始数据中，按照17Hz*6的标准来过滤，会将06 00 00 00 00 00这一标识行忽略，导致无法分隔每一模周期的切割
                if not exemption_from_verification:
                    if res[3] != "06" and res[4] == 0 and res[5] == 0 and res[6] == 0 and res[7] == 0.0 and res[8] == 0:  # 查看源数据发现 会有  空字段 0 0 0 0.0 0
                        pass
                    elif res[3] == "06" and res[4] == 0 and res[5] == 0 and res[6] == 0 and res[7] == 0.0 and res[8] == 0:  # 查看源数据发现 会有  空字段 0 0 0 0.0 0
                        exemption_from_verification = True
                        self.actual_settings_pressure_speed_list.append(res)
                    else:
                        self.actual_settings_pressure_speed_list.append(res)
                else:
                    self.actual_settings_pressure_speed_list.append(res)

        elif frame_bytes[:pressure_size] == "02009E00":  # 统计参数  时间、起点、终点、压力、速度     全过程
            # elif frame_bytes[:pressure_size] == self.Verification_List_dict['统计参数']:  # 统计参数  时间、起点、终点、压力、速度     全过程
            self.processing_statistical_data(frame_bytes)

        elif frame_bytes[:pressure_size] == "02009001":  # 实时机台信号数据                   全过程
            # elif frame_bytes[:pressure_size] == self.Verification_List_dict['边缘计算']:  # 实时机台信号数据                   全过程
            self.processing_signal_data_list.append(self.processing_signal_data(frame_bytes))

    # 信号数据
    # @staticmethod
    def processing_signal_data(self, frame_bytes):
        # round(int((frame_bytes[22:26] + frame_bytes[22:26][:2])[-4:], 16) / 10, 1)
        frame_arr = []
        frame_arr_signal = [0, 0, 0, 0]  # 第一位用来保存射胶或者保压的信息，第二位保存储料，第三位保存射退，第四位保存开模或者合模的信息
        # 日期 0
        frame_arr.append(datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')),  # 日期 0
        # 时间戳 1  毫秒级别
        # frame_arr.append(int(round(time.time() * 1000)))  # 时间戳 1  毫秒级别
        frame_arr.append(time.time())  # 时间戳 1  毫秒级别
        # 帧序列号自行标记
        # 帧序列号 2
        frame_arr.append(0)  # 帧序列号,每秒80帧 2
        # 设定压力 3
        frame_arr.append(0)  # 暂时用0代替
        # 设定速度 4
        frame_arr.append(0)  # 暂时用0代替
        # 实际压力 5
        frame_arr.append(0)  # 暂时用0代替
        # 螺杆位置 6
        frame_arr.append(round(int((frame_bytes[588:592] + frame_bytes[588:592][:2])[-4:], 16) / 10, 1))  # 暂时用0代替

        # 动作信号
        if frame_bytes[28:32] == "0800" and frame_bytes[50:52] != "00":  # 射胶  7   0800 是射胶  不等于00，是只剩射胶、保压、储料三种动作信号了
            if frame_bytes[50:52] == "01":  # 射胶一段
                frame_arr_signal[0] = 11
            elif frame_bytes[50:52] == "02":
                frame_arr_signal[0] = 12
            elif frame_bytes[50:52] == "03":
                frame_arr_signal[0] = 13
            elif frame_bytes[50:52] == "04":
                frame_arr_signal[0] = 14
            elif frame_bytes[50:52] == "05":
                frame_arr_signal[0] = 15
            elif frame_bytes[50:52] == "06":
                frame_arr_signal[0] = 16
            elif frame_bytes[50:52] == "07":
                frame_arr_signal[0] = 17
            elif frame_bytes[50:52] == "08":
                frame_arr_signal[0] = 18
            elif frame_bytes[50:52] == "09":
                frame_arr_signal[0] = 19
        elif frame_bytes[28:32] == "0840" and frame_bytes[50:52] != "00":  # 保压  7  0840 是保压  不等于00，是只剩射胶、保压、储料三种动作信号了
            if frame_bytes[50:52] == "01":  # 保压一段
                frame_arr_signal[0] = 21
            elif frame_bytes[50:52] == "02":
                frame_arr_signal[0] = 22
            elif frame_bytes[50:52] == "03":
                frame_arr_signal[0] = 23
            elif frame_bytes[50:52] == "04":
                frame_arr_signal[0] = 24
            elif frame_bytes[50:52] == "05":
                frame_arr_signal[0] = 25
            elif frame_bytes[50:52] == "06":
                frame_arr_signal[0] = 26
            elif frame_bytes[50:52] == "07":
                frame_arr_signal[0] = 27
            elif frame_bytes[50:52] == "08":
                frame_arr_signal[0] = 28
            elif frame_bytes[50:52] == "09":
                frame_arr_signal[0] = 29
        elif frame_bytes[28:32] == "2000":  # 储料  8
            frame_arr_signal[1] = 1
        elif frame_bytes[28:32] == "1000":  # 射退  9
            frame_arr_signal[2] = 1
        elif frame_bytes[28:32] == "0100":  # 合模  10
            frame_arr_signal[3] = 1
        elif frame_bytes[28:32] == "0400":  # 开模  10
            frame_arr_signal[3] = 4

        frame_arr.extend(frame_arr_signal)

        # 机台状态信号  11
        frame_arr.append(frame_bytes[24:26])

        # 动作信号    冷却信号 和 托模信号   12
        frame_arr.append(frame_bytes[32:36])

        # # 托模信号  13
        # frame_arr.append(frame_bytes[30:34])

        return frame_arr

    # 统计参数
    def processing_statistical_data(self, frame_bytes):
        # round(int((frame_bytes[22:26] + frame_bytes[22:26][:2])[-4:], 16) / 10, 1)
        frame_arr = self.statistical_parameter_row_identification  # 这玩意是个字典
        computer_board_timing_N = round(int((frame_bytes[24:28] + frame_bytes[24:28][:2])[-4:], 16) / 100, 2)  # 第N帧的 计时
        if computer_board_timing_N < self.computer_board_timing:  # 如果第N帧的计时  小于  前一帧的计时  说明 第N帧  是计时 起头的第一帧
            '''
                    这里好像有个bug：新周期的第一点的数据并没有被记录到字典中，而且进入到这里面时，也没有更新self.computer_board_timing的值
                    '''
            self.computer_board_timing = computer_board_timing_N
            # 取本周期内最大值
            if self.scqd:
                self.statistical_parameter_row_identification["射出起点"] = str(max(self.scqd))
            else:
                self.statistical_parameter_row_identification["射出起点"] = ""
            if self.scjy:
                self.statistical_parameter_row_identification["射出尖压"] = str(max(self.scjy))
            else:
                self.statistical_parameter_row_identification["射出尖压"] = ""
            if self.cljy:
                self.statistical_parameter_row_identification["储料尖压"] = str(max(self.cljy))
            else:
                self.statistical_parameter_row_identification["储料尖压"] = ""
            if self.zdss:
                self.statistical_parameter_row_identification["最大射速"] = str(max(self.zdss))
            else:
                self.statistical_parameter_row_identification["最大射速"] = ""
            # # 取下一周期第一点
            # self.statistical_parameter_row_identification["取件时间"] = str(round(int((frame_bytes[208:212] + frame_bytes[208:212][:2])[-4:], 16) / 100, 2))
            self.statistical_parameter_row_identification_True = copy.deepcopy(self.statistical_parameter_row_identification)
            # print('-----------------------------------------------------------------------------------上一周期的统计参数值列表：', self.statistical_parameter_row_identification_True)
            self.del_data()  # 上一个周期的数据已经全部拿到了，将self.scqd, self.scjy, self.cljy, self.zdss四个列表清空，供下一个周期的数据开始存储
            # 取新周期第二点，在这里做一个标记，程序能走到if里面来，就代表这是新周期的第一点，在这里做一个全局的标记
            self.new_circle_first = True  # 将实例属性更新为true


        else:
            self.computer_board_timing = computer_board_timing_N
            frame_arr["周期计时"] = str(round(int((frame_bytes[24:28] + frame_bytes[24:28][:2])[-4:], 16) / 100, 2))  # 这个周期计时是这条数据过来时，这一模产品进行到什么时间了
            frame_arr["注射保压时间"] = str(round(int((frame_bytes[32:36] + frame_bytes[32:36][:2])[-4:], 16) / 100, 2))
            frame_arr["射出时间"] = str(round(int((frame_bytes[40:44] + frame_bytes[40:44][:2])[-4:], 16) / 100, 2))
            frame_arr["储料时间"] = str(round(int((frame_bytes[48:52] + frame_bytes[48:52][:2])[-4:], 16) / 100, 2))
            frame_arr["合模时间"] = str(round(int((frame_bytes[56:60] + frame_bytes[56:60][:2])[-4:], 16) / 100, 2))
            frame_arr["合模低压时间"] = str(round(int((frame_bytes[60:64] + frame_bytes[60:64][:2])[-4:], 16) / 100, 2))
            frame_arr["合模高压时间"] = str(round(int((frame_bytes[64:68] + frame_bytes[64:68][:2])[-4:], 16) / 100, 2))
            frame_arr["开模时间"] = str(round(int((frame_bytes[68:72] + frame_bytes[68:72][:2])[-4:], 16) / 100, 2))
            frame_arr["开模位置"] = str(round(int((frame_bytes[72:76] + frame_bytes[72:76][:2])[-4:], 16) / 10, 1))
            # frame_arr["射胶信号"] = frame_bytes[86:90]
            frame_arr["射出终点"] = str(round(int((frame_bytes[96:100] + frame_bytes[96:100][:2])[-4:], 16) / 10, 1))
            frame_arr["射出监控"] = str(round(int((frame_bytes[104:108] + frame_bytes[104:108][:2])[-4:], 16) / 10, 1))
            frame_arr["转保压力"] = str(int((frame_bytes[120:124] + frame_bytes[120:124][:2])[-4:], 16))
            frame_arr["最大储料转速"] = str(int((frame_bytes[124:128] + frame_bytes[124:128][:2])[-4:], 16))
            frame_arr["射退时间"] = str(round(int((frame_bytes[128:132] + frame_bytes[128:132][:2])[-4:], 16) / 100, 2))
            frame_arr["托模时间"] = str(round(int((frame_bytes[132:136] + frame_bytes[132:136][:2])[-4:], 16) / 100, 2))
            frame_arr["顶进时间"] = str(round(int((frame_bytes[148:152] + frame_bytes[148:152][:2])[-4:], 16) / 100, 2))
            frame_arr["顶退时间"] = str(round(int((frame_bytes[152:156] + frame_bytes[152:156][:2])[-4:], 16) / 100, 2))
            if self.new_circle_first:
                self.new_circle_first = False  # 只要进来一次就将其更新为False,同一个周期内，不会再进入这个if里面更新‘取件时间’的值了
                frame_arr["取件时间"] = str(round(int((frame_bytes[208:212] + frame_bytes[208:212][:2])[-4:], 16) / 100, 2))

            frame_arr["保压时间"] = str(round(int((frame_bytes[280:284] + frame_bytes[280:284][:2])[-4:], 16) / 100, 2))
            frame_arr["冷却时间"] = str(round(int((frame_bytes[284:288] + frame_bytes[284:288][:2])[-4:], 16) / 100, 2))

            self.scqd.append(round(int((frame_bytes[110:114] + frame_bytes[110:114][:2])[-4:], 16) / 10, 1))
            self.scjy.append(int((frame_bytes[140:144] + frame_bytes[140:144][:2])[-4:], 16))
            self.cljy.append(int((frame_bytes[144:148] + frame_bytes[144:148][:2])[-4:], 16))
            self.zdss.append(int((frame_bytes[216:220] + frame_bytes[216:220][:2])[-4:], 16))

            self.statistical_parameter_row_identification = frame_arr

    @staticmethod
    def verify_dictionary(frame_bytes, verification_List, verification_List_del_len):
        for i, j in enumerate(verification_List):
            if frame_bytes == j:
                del_len = verification_List_del_len[i]
                return True, int(del_len / 2)

    # 统计周期区间
    @staticmethod
    def statistical_cycle_interval(Last_50_cycles, zhenshu):  # 将周期列表、设置样本长度传过来
        # logger.info("周期列表个数{}，到{}，周期帧数限制".format(len(Last_50_cycles), zhenshu))
        dict_qujian = {}
        for i in Last_50_cycles:
            dict_qujian[str(i // 5)] = 0
        for i in Last_50_cycles:
            dict_qujian[str(i // 5)] += 1
        ans = max(dict_qujian, key=lambda x: dict_qujian[x])
        standard_cycle = (eval(ans) + 1) * 5
        # logger.info("落在多数区间的上限值是{}s".format(standard_cycle))
        return standard_cycle

    @staticmethod
    def add_increment(frame_length=None):
        update_product(UpdateType.ADD_GOOD, frame_length=frame_length)

    # 模拟及开关信号示例数据
    @staticmethod
    def is_pressure_frame(unknown_bytes):  # 0:帧头, 1:dest,3:数据长度, 17:帧尾
        check_bytes = unknown_bytes[1:18]  # 从第2字节到第16字节, 需要校验的字节段
        check_result = unknown_bytes[18]  # 第17字节, 异或校验和
        if unknown_bytes[0] == 0xAA and unknown_bytes[1] == 0xff and unknown_bytes[3] == 18 \
                and unknown_bytes[4] == 0x01 and unknown_bytes[19] == 0xAA:
            bbc = 0x00  # 0异或任何数为任何数本身
            for byte in check_bytes:
                bbc ^= byte
            return bbc == check_result
        else:
            return False

    # K型热电偶温度示例数据
    @staticmethod
    def is_temp_frame(unknown_bytes):
        check_bytes = unknown_bytes[1:13]
        check_result = unknown_bytes[13]
        if unknown_bytes[0] == 0xAA and unknown_bytes[1] == 0xff and unknown_bytes[3] == 13 \
                and unknown_bytes[4] == 0x02 and unknown_bytes[14] == 0xAA:
            bbc = 0x00  # 0异或任何数为任何数本身
            for byte in check_bytes:
                bbc ^= byte
            return bbc == check_result
        else:
            return False

    # 1后面5个0 才能确定是一个产品的结束
    # 10是开模，9是射退
    @staticmethod
    def is_product_begin(check_frames):
        current_frame = check_frames[0]
        check_frame_list = check_frames[1:5]
        if int(current_frame[10]) == 1:
            flag = True
            for frame in check_frame_list:
                if int(frame[10]) == 1:
                    flag = False
                    break
        else:
            flag = False
        return flag

    # 1后面5个0 才能确定是一个产品的结束
    # 10是开模，9是射退
    @staticmethod
    def is_product_begin_for_other(check_frames):
        current_frame = check_frames[0]
        check_frame_list = check_frames[1:5]
        if str(current_frame[3]) == "06":
            flag = True
            for frame in check_frame_list:
                if str(frame[3]) == "06":
                    flag = False
                    break
        else:
            flag = False
        return flag

    @staticmethod
    def calc_crc(string):
        data = bytearray.fromhex(string)
        # print(data)
        crc = 0xFFFF  # 初始值
        for pos in data:
            crc ^= pos  # 每次两位16进制和crc低8位异或
            for i in range(8):  # 右移八次
                if (crc & 1) != 0:  # 如果移出去的不是0（即移出去的是1）则右移1位且和A001异或。否则为0直接右移1位不作其他处理
                    crc >>= 1
                    crc ^= 0xA001
                else:
                    crc >>= 1
        ret = hex(((crc & 0xff) << 8) + (crc >> 8))[2:]  # 高低8位对调。
        if len(ret) != 4:
            ret = '0' * (4 - len(ret)) + ret
        return ret

    @staticmethod
    def transfer_pressure_frame_to_arr(frame_bytes):
        frame_arr = []
        # 日期 0
        frame_arr.append(datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')),  # 日期 0
        # 时间戳 1  毫秒级别
        frame_arr.append(int(round(time.time() * 1000)))  # 时间戳 1  毫秒级别
        # 帧序列号自行标记
        # 帧序列号 2
        frame_arr.append(0)  # 帧序列号,每秒80帧 2
        # 设定压力 3
        frame_arr.append(round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[6:14]))))[0], 10))  # 设定压力 3
        # 设定速度 4
        frame_arr.append(round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[14:22]))))[0], 10))  # 设定速度 4
        # 实际压力 5
        frame_arr.append(round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[22:30]))))[0], 10))  # 实际压力 5
        # 螺杆位置 6
        frame_arr.append(round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[30:38]))))[0], 10))  # 螺杆位置 6

        sj = 1
        if round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[38:46]))))[0], 10) >= 22:
            sj = 0
        # 射胶信号 7
        frame_arr.append(sj)  # 射胶信号 7  # 电压值大于22V为1，小于2V为0

        cl = 1
        if round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[46:54]))))[0], 10) >= 22:
            cl = 0
        # 储料信号 8
        frame_arr.append(cl)  # 储料信号 8

        st = 1
        if round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[54:62]))))[0], 10) >= 22:
            st = 0
        # 射退信号 9
        frame_arr.append(st)  # 射退信号 9

        km = 1
        if round(struct.unpack('<f', struct.pack('<I', eval('0x' + (frame_bytes[62:70]))))[0], 10) >= 22:
            km = 0
        # 开模信号 10  # 电压值大于22V为1，小于2V为0
        frame_arr.append(km)
        return frame_arr

    @staticmethod
    def temp_frames_to_arr(tem_bytes):
        tem_arr = list()
        tem_arr.append(datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))  # 日期
        tem_arr.append(int(round(time.time() * 1000)))  # 时间戳
        tem_arr.append(tem_bytes[5] * 256 + tem_bytes[6])  # 第一段温度
        tem_arr.append(tem_bytes[7] * 256 + tem_bytes[8])  # 第二段温度
        tem_arr.append(tem_bytes[9] * 256 + tem_bytes[10])  # 第三段温度
        tem_arr.append(tem_bytes[11] * 256 + tem_bytes[12])  # 第三段温度
        return tem_arr


class UpdateType(Enum):
    ADD_GOOD = 2
    ADD_BAD = 3
    POS_FEEDBACK = 1  # 良品+1同时不良品-1
    NEG_FEEDBACK = -1  # 不良+1 同时良品-1


def bytes2hex(frame_bytes):
    hex_bytes = binascii.b2a_hex(frame_bytes)
    frame_bytes_str = hex_bytes.decode('utf-8').upper()
    return frame_bytes_str


def update_product(update_type=UpdateType.ADD_GOOD, frame_length=None):
    url = settings.SERVER_URL
    pad_url = '{}/pad/pad'.format(url)
    product_url = f"{pad_url}/updateNew/{settings.MACHINE_CODE}/{frame_length}"
    get(product_url, None)


def get(url, data):
    try:
        response = requests.get(url, data, timeout=(3.05, 27))
        # response = requests.put(url, data, timeout=(3.05, 27))
        OK_CODE = 200
        if response.status_code == OK_CODE:
            logger.info(f'{url}:{response.json()}')
            result = analyse_response(response.json())
            # by zxy on 20191114
            response.close()
            return result
        else:
            logger.error(f"{response},网络异常,无法成功访问接口")
    except Exception as e:
        logger.error(e)


def analyse_response(result):
    SUCCESS_CODE = 0
    if result["code"] == SUCCESS_CODE:
        return result["data"]
    else:
        logger.error(result['msg'])
